﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.ComponentModel;
using SB.Logging;

namespace SB.Tools
{
    public class PropertyComparer<T> : System.Collections.Generic.IComparer<T>
    {
        private static readonly ILogger log = LoggingFacade.GetLogger(typeof(PropertyComparer<T>));
        
        private PropertyDescriptor _property;
        private ListSortDirection _direction;

        public PropertyComparer(PropertyDescriptor property,
            ListSortDirection direction)
        {
            _property = property;
            _direction = direction;
        }

        public int Compare(T col1, T col2)
        {
            object col1Value = GetPropertyValue(col1,
                               _property.Name);

            object col2Value = GetPropertyValue(col2,
                               _property.Name);

            if (_direction == ListSortDirection.Ascending)
            {
                return CompareAscending(col1Value,
                                        col2Value);
            }
            else
            {
                return CompareDescending(col1Value,
                                         col2Value);
            }
        }

        public bool Equals(T col1, T col2)
        {
            return col1.Equals(col2);
        }

        public int GetHashCode(T obj)
        {
            return obj.GetHashCode();
        }

        private int CompareAscending(object x, object y)
        {
            int result;

            if (x == null && y != null)
            {
                if (y.GetType() == typeof(DateTime))
                    x = default(DateTime);
            }

            if (y == null && x != null)
            {
                if (x.GetType() == typeof(DateTime))
                    y = default(DateTime);
            }

            if (x == null)
                x = "";

            if (y == null)
                y = "";

            if (x is IComparable)
            {
                result = ((IComparable)x).CompareTo(y);
            }
            else if (x.Equals(y))
            {
                result = 0;
            }
            else result = (x.ToString()).CompareTo(y.ToString());

            return result;
        }

        private int CompareDescending(object x, object y)
        {
            return -CompareAscending(x, y);
        }

        private object GetPropertyValue(T value, string
                                        property)
        {
            PropertyInfo propertyInfo =
            value.GetType().GetProperty(property);

            return propertyInfo.GetValue(value, null);
        }
    }
}
